# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
-import os,sys,re,subprocess
+import os,sys,re,subprocess,tempfile,shutil
+import argparse
-i=1
-repo=sys.argv[i]
-i += 1
-chroot_path=sys.argv[i]
-i += 1
-args=sys.argv[i:]
+def get_build_env():
+ return {'HOME' : '/',
+ 'HOSTNAME' : 'ostbuild',
+ 'LANG': 'C',
+ 'PATH' : '/usr/bin:/bin:/usr/sbin:/sbin',
+ 'SHELL' : '/bin/bash',
+ 'TERM' : 'vt100',
+ 'TMPDIR' : '/tmp',
+ 'TZ': 'EST5EDT'
+ }
-if os.getuid() != 0:
- print "This program must be run as root."
- sys.exit(1)
-rootdir=os.path.join(chroot_path, 'root')
+parser = argparse.ArgumentParser(description="Build a module in a given root")
+parser.add_argument('--repo')
+parser.add_argument('--resultdir')
+parser.add_argument('--branch')
+parser.add_argument('--debug-shell', type=bool)
-if not os.path.isdir(rootdir):
- print "Not a directory: %s" % (rootdir, )
- sys.exit(1)
+args = parser.parse_args()
-builddir = os.path.join(rootdir, 'ostree-build')
-if not os.path.isdir(builddir):
- os.mkdir(builddir)
+def log(m):
+ sys.stdout.write(m)
+ sys.stdout.write('\n')
+ sys.stdout.flush()
+tmpdir = tempfile.mkdtemp(prefix='ostree-chroot-compile-')
+log("Using temporary directory: %s" % (tmpdir, ))
-def run_in_chroot(args):
- proc_path=os.path.join(chroot_path, 'proc')
- subprocess.check_call(['mount', '-t', 'proc', 'proc', proc_path])
+child_tmpdir=os.path.join(tmpdir, 'tmp')
+os.mkdir(child_tmpdir)
- try:
- subprocess.check_call(['chroot', chroot_path])
- finally:
- subprocess.call(['umount', proc_path])
+rev = subprocess.check_output(['ostree', '--repo=' + args.repo, 'rev-parse', args.branch])
+rev=rev.strip()
-run_in_chroot(args)
+rootdir = os.path.join(tmpdir, 'root-' + rev)
+subprocess.check_call(['ostree', '--repo=' + args.repo, 'checkout', '-U', rev, rootdir])
+log("Checked out root: %s" % (rootdir, ))
+
+builddir = os.path.join(rootdir, 'ostbuild');
+os.mkdir(builddir)
+os.mkdir(os.path.join(builddir, 'source'))
+os.mkdir(os.path.join(builddir, 'results'))
+
+# We need to search PATH here manually so we correctly pick up an
+# ostree install in e.g. ~/bin even though we're going to set PATH
+# below for our children inside the chroot.
+ostbuild_user_chroot_path = None
+for dirname in os.environ['PATH'].split(':'):
+ path = os.path.join(dirname, 'ostbuild-user-chroot')
+ if os.access(path, os.X_OK):
+ ostbuild_user_chroot_path = path
+ break
+if ostbuild_user_chroot_path is None:
+ ostbuild_user_chroot_path = 'ostbuild-user-chroot'
+
+child_args = [ostbuild_user_chroot_path, '--unshare-pid', '--unshare-net', '--unshare-ipc',
+ '--mount-readonly', '/',
+ '--mount-proc', '/proc',
+ '--mount-bind', '/dev', '/dev',
+ '--mount-bind', child_tmpdir, '/tmp',
+ '--mount-bind', os.getcwd(), '/ostbuild/source',
+ '--mount-bind', args.resultdir, '/ostbuild/results',
+ rootdir,
+ '/bin/sh']
+if not args.debug_shell:
+ child_args += ['-c',
+ 'cd /ostbuild/source && ostbuild-compile-one-impl OSTBUILD_RESULTDIR=/ostbuild/results'
+ ]
+log("Running: %r" % (child_args, ))
+subprocess.check_call(child_args, env=get_build_env())
+
+shutil.rmtree(tmpdir)
+
for arg in sys.argv[1:]:
if arg.startswith('OSTBUILD_RESULTDIR='):
- ostbuild_resultdir=arg[20:]
+ ostbuild_resultdir=arg[len('OSTBUILD_RESULTDIR='):]
elif arg.startswith('--'):
configargs.append(arg)
else:
def run_sync(args, cwd=None, env=None):
log("running: %r" % (args,))
f = open('/dev/null', 'r')
+ # This dance is necessary because we want to keep the PWD
+ # environment variable up to date. Not doing so is a recipie
+ # for triggering edge conditions in pwd lookup.
+ if (cwd is not None) and (env is None or ('PWD' in env)):
+ if env is None:
+ env_copy = os.environ.copy()
+ else:
+ env_copy = env.copy()
+ if ('PWD' in env_copy) and (not cwd.startswith('/')):
+ env_copy['PWD'] = os.path.join(env_copy['PWD'], cwd)
+ else:
+ env_copy['PWD'] = cwd
+ else:
+ env_copy = env
proc = subprocess.Popen(args, stdin=f, stdout=sys.stdout, stderr=sys.stderr,
- close_fds=True, cwd=cwd, env=env)
+ close_fds=True, cwd=cwd, env=env_copy)
f.close()
returncode = proc.wait()
log("pid %d exited with code %d" % (proc.pid, returncode))
if bootstrap:
log("Detected bootstrap script: %s, using it" % (bootstrap, ))
args = [bootstrap]
- args.extend(configargs)
# Add NOCONFIGURE; GNOME style scripts use this
env = dict(os.environ)
env['NOCONFIGURE'] = '1'
shutil.copytree('.', '_build', symlinks=True,
ignore=shutil.ignore_patterns('_build'))
use_builddir = False
- builddir = '.'
- else:
- builddir = '_build'
- if not use_builddir:
- configdir = './'
- else:
- configdir = os.getcwd()
- builddir = builddir
+ if use_builddir:
+ builddir = '_build'
log("Using build directory %r" % (builddir, ))
if not os.path.isdir(builddir):
os.mkdir(builddir)
configstatus = 'config.status'
if not os.path.exists(configstatus):
- args = [os.path.join(configdir, 'configure')]
+ if use_builddir:
+ args = ['../configure']
+ else:
+ args = ['./configure']
args.extend(configargs)
- run_sync(args, cwd=builddir)
+ if use_builddir:
+ run_sync(args, cwd=builddir)
+ else:
+ run_sync(args)
else:
log("Found %s, skipping configure" % (configstatus, ))
phase_build(builddir=builddir)
phase_make_artifacts(builddir=builddir)
-def make_artifact(name, from_files, fakeroot_temp=None, tempdir=None, resultdir=None):
+def make_artifact(name, from_files, tempdir=None, resultdir=None):
targz_name = name + '.tar.gz'
(fd,filelist_temp)=tempfile.mkstemp(prefix='ostree-filelist-%s' % (name, ))
os.close(fd)
f.write(filename)
f.write('\n')
f.close()
- if fakeroot_temp:
- args = ['fakeroot', '-i', fakeroot_temp]
- else:
- args = []
if resultdir:
result_path = os.path.join(resultdir, targz_name)
else:
result_path = targz_name
- args.extend(['tar', '-c', '-z', '-C', tempdir, '-f', result_path, '-T', filelist_temp])
+ args = ['tar', '-c', '-z', '-C', tempdir, '-f', result_path, '-T', filelist_temp]
run_sync(args)
log("created: %s" % (os.path.abspath (result_path), ))
artifact_prefix='artifact-%s-%s,%s' % (build_target, basename, version)
- if os.getuid() != 0:
- (fd,fakeroot_temp)=tempfile.mkstemp(prefix='ostree-fakeroot-%s-' % (basename,))
- os.close(fd)
- tempfiles.append(fakeroot_temp)
- else:
- fakeroot_temp = None
tempdir = tempfile.mkdtemp(prefix='ostree-build-%s-' % (basename,))
tempfiles.append(tempdir)
- if fakeroot_temp is not None:
- args = ['fakeroot', '-s', fakeroot_temp]
- else:
- args = []
- args.extend(['make', 'install', 'DESTDIR=' + tempdir])
+ args = ['make', 'install', 'DESTDIR=' + tempdir]
run_sync(args, cwd=builddir)
devel_files = set()
os.chdir(oldpwd)
if devel_files:
- make_artifact(artifact_prefix + '-devel', devel_files, fakeroot_temp=fakeroot_temp, tempdir=tempdir, resultdir=ostbuild_resultdir)
- make_artifact(artifact_prefix + '-runtime', runtime_files, fakeroot_temp=fakeroot_temp, tempdir=tempdir, resultdir=ostbuild_resultdir)
+ make_artifact(artifact_prefix + '-devel', devel_files, tempdir=tempdir, resultdir=ostbuild_resultdir)
+ make_artifact(artifact_prefix + '-runtime', runtime_files, tempdir=tempdir, resultdir=ostbuild_resultdir)
def phase_complete():
for tmpname in tempfiles: